package com.cma.common.email;

import com.cma.common.os.OsInfoUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.velocity.VelocityEngineUtils;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import javax.mail.util.ByteArrayDataSource;
import java.util.Map;

/**
 * Created by baijs on 2016/8/3.
 */
public class MailService {
    private static final Log logger = LogFactory.getLog(MailService.class);

    @Autowired
    private JavaMailSender javaMailSender;
    @Autowired
    private SimpleMailMessage simpleMailMessage;
    @Autowired
    private TaskExecutor taskExecutor;
    @Autowired
    private VelocityEngine velocityEngine;

    /**
     * 发送邮件
     *
     * @param content 邮件内容
     */
    public void send(String content) {
        String[] to = simpleMailMessage.getTo();
        String subject = simpleMailMessage.getSubject();
        sendTask(to, subject, content);
    }

    /**
     * 发送邮件
     *
     * @param subject 主题
     * @param content 内容
     */
    public void send(String subject, String content) {
        String[] to = simpleMailMessage.getTo();
        sendTask(to, subject, content);
    }

    /**
     * 发送邮件
     *
     * @param to      收件人
     * @param subject 主题
     * @param content 内容
     */
    public void send(String[] to, String subject, String content) {
        sendTask(to, subject, content);
    }

    /**
     * 通过velocity模板发送邮件
     *
     * @param mailVMBean
     */
    public void sendByVM(MailVMBean mailVMBean) {
        if (mailVMBean == null || mailVMBean.getObjectMap() == null || mailVMBean.getTemplatePath() == null) {
            logger.error("发送邮件失败：变量 MailVMBean 设置不正确");
            return;
        }
        String[] to = mailVMBean.getTo() == null ? simpleMailMessage.getTo() : mailVMBean.getTo();
        String subject = mailVMBean.getSubject() == null ? simpleMailMessage.getSubject() : mailVMBean.getSubject();
        String templatePath = mailVMBean.getTemplatePath();
        Map velocityContext = mailVMBean.getObjectMap();

        String content = "";
        try {
            content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templatePath, "utf-8", velocityContext);
        } catch (Exception e) {
            logger.error("发送邮件失败：模板[" + templatePath + "]内容初始化失败,错误信息：" + e.getMessage());
        }
        if ("".equals(content)) {
            logger.error("发送邮件失败:邮件内容为空");
            return;
        }
        sendTask(to, subject, content);

    }

    private void sendTask(String[] to, String subject, String content) {
        if (OsInfoUtil.isWindows() || OsInfoUtil.isMacOSX() || OsInfoUtil.isMacOS()) {
            logger.error("开发环境不发送邮件【to:["+to+"]===>subject:["+subject+"]===>content["+content+"]】");
        } else {
            try {
                taskExecutor.execute(new SendMailThread(to, subject, content));
            } catch (Exception e) {
                logger.error("发送邮件线程池报错：" + e.getMessage());
            }
        }
    }

    private void sendMail(String[] to, String subject, String content) {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
            messageHelper.setFrom(simpleMailMessage.getFrom());
            messageHelper.setSubject(subject);
            messageHelper.setTo(to);
            messageHelper.setText(content, true);
            javaMailSender.send(message);
            logger.info("邮件发送成功：TO->[ " + StringUtils.join(to, ",") + " ], CONTENT->[ " + content + " ]");
        } catch (MessagingException e) {
            e.printStackTrace();
            logger.error("邮件发送失败：TO->[" + StringUtils.join(to, ",") + "], CONTENT->[ " + content + " ], ERROR:" + e.getMessage());
        }
    }

    public void send(String subject, String content, String filename, ByteArrayDataSource bar) {
        sendTask(simpleMailMessage.getTo(), subject, content, filename, bar);
    }

    public void send(String[] to, String subject, String content, String filename, ByteArrayDataSource bar) {
        sendTask(to, subject, content, filename, bar);
    }

    private void sendTask(String[] to, String subject, String content, String filename, ByteArrayDataSource bar) {
        if (OsInfoUtil.isWindows() || OsInfoUtil.isMacOSX() || OsInfoUtil.isMacOS()) {
            logger.error("开发环境不发送邮件");
        } else {
            try {
                taskExecutor.execute(new SendMailThread(to, subject, content, filename, bar));
            } catch (Exception e) {
                logger.error("发送邮件线程池报错：" + e.getMessage());
            }
        }
    }
    private void sendMail(String[] to, String subject, String content, String filename, ByteArrayDataSource bar) {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
            messageHelper.setFrom(simpleMailMessage.getFrom());
            messageHelper.setSubject(subject);
            messageHelper.setTo(to);
            messageHelper.setText(content, true);
            messageHelper.addAttachment(MimeUtility.encodeWord(filename),bar);
            javaMailSender.send(message);
            logger.info("邮件发送成功：TO->[ " + StringUtils.join(to, ",") + " ], CONTENT->[ " + content + " ]");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("邮件发送失败：TO->[" + StringUtils.join(to, ",") + "], CONTENT->[ " + content + " ], ERROR:" + e.getMessage());
        }
    }

    /**
     * 线程类
     */
    //modify by huyaowu 20160811 增加发送附件
    private class SendMailThread implements Runnable {
        private String[] to;
        private String subject;
        private String content;
        private String filename;
        private ByteArrayDataSource byteArrayDataSource;



        private SendMailThread(String[] to, String subject, String content) {
            super();
            this.to = to;
            this.subject = subject;
            this.content = content;
        }
        private SendMailThread(String[] to, String subject, String content, String filename, ByteArrayDataSource byteArrayDataSource) {
            super();
            this.to = to;
            this.subject = subject;
            this.content = content;
            this.filename = filename;
            this.byteArrayDataSource = byteArrayDataSource;
        }

        @Override
        public void run() {
            if(StringUtils.isNotBlank(this.filename)&&null != byteArrayDataSource){
                sendMail(to, subject, content, filename, byteArrayDataSource);
            }else {
                sendMail(to, subject, content);
            }
        }
    }
}
